#include "formdcsnetsetting.h"
#include "ui_formdcsnetsetting.h"

#include "udpworker.h"
#include "dcsproto/proto.h"

#include <QTimer>
#include <QMessageBox>
#include <QDebug>
#include <global.h>

FormDCSNetSetting::FormDCSNetSetting(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::FormDCSNetSetting)
{
    ui->setupUi(this);

    setWindowFlags(windowFlags() | Qt::Dialog);
    setWindowModality(Qt::ApplicationModal);
    setAttribute(Qt::WA_DeleteOnClose);

    numberkeyboard = new DialogVKB(this);

    //将所有lineedit信号都和软件盘界面显示关联
    connect(ui->lineEditSlaveNumSetting, SIGNAL(send_show(QString)), this, SLOT(show_numberkeyboard_ui(QString)));
    connect(numberkeyboard, SIGNAL(sendMessage(QString)), this, SLOT(confirmString(QString)));

    mDbopt = new DCSDbOperator();
    quint8 iface;
    if (!DCSDbOperator::getMasterParameterInterface(iface))
    {
        qDebug() << "db get interface error,set to default";
        iface = UDP_IFACE_EN_WAN;
    }

    if (iface == UDP_IFACE_EN_WAN)
    {
        mUdp = new UdpWorker(INTERFACE_WAN_NAME);
    }
    else
    {
        mUdp = new UdpWorker(INTERFACE_LAN_NAME);
    }
    ui->comboBoxIface->setCurrentIndex(iface);

    ui->progressBar->hide();

    //默认设置分控个数为1个
    if (DCSDbOperator::getMasterParameterSlaveNum(mSlaveNum))
    {
        ui->lineEditSlaveNumSetting->setText(QString("").setNum(mSlaveNum));
    }
    else
    {
        ui->lineEditSlaveNumSetting->setText("1");
        DCSDbOperator::setMasterParameterSlaveNum(1);
    }

    mcurReadId = 1;

    //发自动地址分配广播的定时器，第一次间隔为200ms，超时函数里面修改为5000ms
    mAutoAddrTimer.setSingleShot(false);
    mAutoAddrTimer.setInterval(200);
    mAutoAddrTimer.start();
    connect(&mAutoAddrTimer, &QTimer::timeout, this, &FormDCSNetSetting::on_autoAddrTimerout);


    connect(&mCmdSendTimer, &QTimer::timeout, this, &FormDCSNetSetting::on_cmdSendTimerout);
    connect(mUdp, &UdpWorker::dataRecvdBytes, this, &FormDCSNetSetting::on_dataRecved);
    connect(ui->lineEditSlaveNumSetting, &VKB_lineEdit::textChanged, this,
            &FormDCSNetSetting::onSlaveNumSettingChanged);

    connect(ui->comboBoxIface, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
            &FormDCSNetSetting::onInterFaceChanged);

    qDebug() << "[FormDCSNetSetting] \t Constructor";
}

FormDCSNetSetting::~FormDCSNetSetting()
{
    delete ui;
    delete mUdp;
    delete mDbopt;
    qDebug() << "[FormDCSNetSetting] \t Destructor";
}

void FormDCSNetSetting::on_pushButtonDCSNetSettingReturn_clicked()
{
    this->close();
}

void FormDCSNetSetting::on_pushButtonDCSNetSettingModify_clicked()
{
    char buf[60];

    mSlaveNum = ui->lineEditSlaveNumSetting->text().toInt();
    DCSDbOperator::setMasterParameterSlaveNum(mSlaveNum);
    //初始化一些读取过程用到的变量
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(mSlaveNum);
    ui->progressBar->setValue(0);
    ui->progressBar->show();

    mcurReadId = 1;
    mReadFailedIdvec.clear();
    mReadOkIdvec.clear();

    //广播设置分控网络千百兆模式
    struct slave_netspeed_set_pdu pdu{};
    memset(buf, 0x0, sizeof(buf));
    memset(&pdu, 0x0, sizeof(pdu));
    pdu.mode = EN_SLAVE_NETSPEED_100M;
    aklt_proto_encode((unsigned char *) buf, TYP_SLAVE_BROADCAST_OCCA_SET, CMD_SLAVE_NETSPEED_SET, 10000,
                      (unsigned char *) &pdu, sizeof(pdu), SLAVE_BROADCAST);

    mUdp->dataSend(buf, 60);

    //启动定时器，5秒后发送ID自动分配命令
    mCmdSendTimer.setSingleShot(true);
    mCmdSendTimer.setInterval(5000);
    mCmdSendTimer.start();
}

void FormDCSNetSetting::on_cmdSendTimerout()
{
    char buf[60];
    struct slave_id_set_pdu idSetPdu{};
    struct slave_conf_read_pdu pdu{};

    if (mCmdSendTimer.interval() == 5000)
    {
        //ID自动分配命令
        memset(buf, 0x0, sizeof(buf));
        memset(&idSetPdu, 0x0, sizeof(idSetPdu));
        idSetPdu.type = EN_SLAVE_ID_SET_TYPE_AUTO;
        idSetPdu.param.fist_para.id = 0x001;
        aklt_proto_encode((unsigned char *) buf, TYP_SLAVE_BROADCAST_FREQ_SET, CMD_SLAVE_ID_CONF_FREQ_SET, 10000,
                          (unsigned char *) &idSetPdu, sizeof(idSetPdu), SLAVE_BROADCAST);
        mUdp->dataSend(buf, 60);


        mCmdSendTimer.setSingleShot(false);
        mCmdSendTimer.setInterval(100);
        mCmdSendTimer.start();
    }
    else
    {
        if (mcurReadId <= mSlaveNum)
        {
            ui->progressBar->setValue(mcurReadId - 1);

            //单播读取网络模式
            memset(buf, 0x0, sizeof(buf));
            memset(&pdu, 0x0, sizeof(pdu));
            pdu.conf_id = SLAVE_CONF_NETMODE;
            aklt_proto_encode((unsigned char *) buf, TYP_SLAVE_CONF_READ, CMD_SLAVE_CONF_READ, mcurReadId,
                              (unsigned char *) &pdu, sizeof(pdu), SLAVE_UNICAST);
            mUdp->dataSend(buf, 60);


            if (!mUdp->waitForRecvBytes(2000))
            {
                mReadFailedIdvec.append(mcurReadId);
                qDebug() << "append failed id:" << mcurReadId;
            }

            mcurReadId++;
        }
        else
        {
            ui->progressBar->hide();

            QVector<int>::iterator iter;
            QString tips;

            if (!mReadOkIdvec.empty())
            {
                tips.append(tr("操作成功："));
                for (iter = mReadOkIdvec.begin(); iter != mReadOkIdvec.end(); iter++)
                {
                    tips.append(QString::number(*iter));
                    qDebug() << "read ok id:" << *iter;
                    tips.append(",");
                }
            }

            if (!mReadFailedIdvec.empty())
            {
                tips.append(tr("操作失败："));
                for (iter = mReadFailedIdvec.begin(); iter != mReadFailedIdvec.end(); iter++)
                {
                    tips.append(QString::number(*iter));
                    qDebug() << "read failed id:" << *iter;
                    tips.append(",");
                }
            }


            QMessageBox::information(this,
                                     tr("分控强制百兆"),
                                     tips,
                                     QMessageBox::Ok,
                                     QMessageBox::Ok);

            mCmdSendTimer.stop();
        }
    }
}

/**
 * @brief FormDCSNetSetting::on_autoAddrTimerout
 * 进入网络模式设置界面，周期发自动地址分配命令
 */
void FormDCSNetSetting::on_autoAddrTimerout()
{
    char buf[60];

    //发ID自动分配命令
    struct slave_id_set_pdu pdu{};
    memset(buf, 0x0, sizeof(buf));
    memset(&pdu, 0x0, sizeof(pdu));
    pdu.type = EN_SLAVE_ID_SET_TYPE_AUTO;
    pdu.param.fist_para.id = 0x001;
    aklt_proto_encode((unsigned char *) buf, TYP_SLAVE_BROADCAST_FREQ_SET, CMD_SLAVE_ID_CONF_FREQ_SET, 0x0000,
                      (unsigned char *) &pdu, sizeof(pdu), SLAVE_BROADCAST);
    mUdp->dataSend(buf, 60);

    mAutoAddrTimer.setInterval(5000);
}

void FormDCSNetSetting::on_dataRecved(QByteArray &data)
{
    struct akltproto aklt{};
    aklt_proto_decode(&aklt, (unsigned char *) (data.data()), data.size());
    auto *ack = (struct slave_conf_ack_pdu *) (aklt.data);
    if (ack->finished && aklt.cmd == CMD_SLAVE_NETSPEED_ACK && aklt.type == TYP_SLAVE_CONF_ACK)
    {
        mReadOkIdvec.append(mcurReadId);
        qDebug() << "append ok id:" << mcurReadId;
    }
    else
    {
        mReadFailedIdvec.append(mcurReadId);
        qDebug() << "append failed id:" << mcurReadId;
    }
    delete aklt.data;

}


void FormDCSNetSetting::show_numberkeyboard_ui(const QString &data)
{
    lineEdit_object = sender()->objectName();//获得调用软件盘的部件的名称
    numberkeyboard->setInputdata(data);
    numberkeyboard->show();
}

void FormDCSNetSetting::confirmString(const QString &gemfield)
{
    //判断应该将信息写入哪一个输入框
    if (lineEdit_object == ui->lineEditSlaveNumSetting->objectName())
    {
        ui->lineEditSlaveNumSetting->setText(gemfield);
    }
}

void FormDCSNetSetting::onSlaveNumSettingChanged(const QString &text)
{
    quint32 slaveNum;

    slaveNum = text.toUInt();
    if (slaveNum > 128)
    {
        qDebug() << "slave num too large, set to default";
        slaveNum = 128;
    }

    DCSDbOperator::setMasterParameterSlaveNum(slaveNum);
}

void FormDCSNetSetting::onInterFaceChanged(int index)
{
    if (index > UDP_IFACE_EN_LAN || index < UDP_IFACE_EN_WAN)
    {
        index = UDP_IFACE_EN_WAN;
    }

    if (!mDbopt->setMasterParameterInterface(index))
    {
        qDebug() << "set interface error";
    }

    //清除原来的绑定关系
    disconnect(mUdp, &UdpWorker::dataRecvdBytes, this, &FormDCSNetSetting::on_dataRecved);
    delete mUdp;

    //重新创建对象
    if (index == UDP_IFACE_EN_WAN)
    {
        mUdp = new UdpWorker(INTERFACE_WAN_NAME);
    }
    else
    {
        mUdp = new UdpWorker(INTERFACE_LAN_NAME);
    }
    connect(mUdp, &UdpWorker::dataRecvdBytes, this, &FormDCSNetSetting::on_dataRecved);
}
